﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AIProject.Pylos;

namespace AIProject.Search
{
    class NodeInfo
    {
        private int depthLimit;
        private Boolean isWhite;

        public int DepthLimit
        {
            get
            {
                return this.depthLimit;
            }
            set
            {
                this.depthLimit = value;
            }
        }

        public Boolean IsWhite
        {
            get
            {
                return this.isWhite;
            }
            set
            {
                this.isWhite = value;
            }
        }

        public NodeInfo(int depthLimit, Boolean isWhite)
        {
            this.depthLimit = depthLimit;
            this.isWhite = isWhite;
        }

        public Boolean isTerminal(Node node)
        {
            return node.State.WhiteWon || node.State.BlackWon || node.State.Tie;
        }

        public double utility(Node node)
        {
            State b = node.State;
            double utility = 0;

            if (b.WhiteWon)
            {
                return Double.PositiveInfinity;
            }
            else if (b.BlackWon)
            {
                return Double.NegativeInfinity;
            }

            utility = (b.WhiteReservePieces - b.BlackReservePieces);

            //utility += 2 * (numMoveablePieces(true, b) - numMoveablePieces(false, b));

           // double[] boardPos = valueBoardPosition(b);

            //utility += (boardPos[0] - boardPos[1]);

            return (b.Tie ? (utility / 4.0) : utility);
        }

        public SortedList<int, Pylos.Action> generateRemovals(Node node)
        {
            SortedList<int, Pylos.Action> removals = new SortedList<int, Pylos.Action>();
            List<Pylos.Action> actions = node.State.getActions();

            foreach (Pylos.Action arc in actions)
            {

                if (arc[1] != null) //moves[1] and moves[2] are removals
                {
                    if (arc[2] != null)
                    {
                        removals.Add(1, arc); //removing two pieces is more likely to force alpha-beta cutoff so we consider it first.
                    }
                    else
                    {
                        removals.Add(2, arc);
                    }
                }
            }

            return removals;
        }

        private int numMoveablePieces(Boolean white, State b)
        {
            Piece[,] board = b.Pieces;

            int moveablePieces = 0;

            for (int x = 0; x < 9; x++)
            {
                for (int y = 0; y < ((x < 4) ? 4 : ((x < 7) ? 3 : 2)); y++)
                {
                    if (board[y, x] != null && (board[y, x].OwnedByWhite == white) && board[y, x].Moveable)
                    {
                        moveablePieces++;
                    }
                }
            }

            return moveablePieces;
        }

        private double[] valueBoardPosition(State b)
        {
            double[] toReturn = new double[2];

            for (int i = 4; i < 9; i++)
            {
                for (int j = 3; j < (i < 7 ? 3 : 2); j++)
                {
                    if (b.Pieces[j, i] != null)
                    {
                        if (b.Pieces[j, i].OwnedByWhite == true && b.Pieces[j, i].Location.X < 7)
                        {
                            toReturn[0] += 0.5;
                        }
                        else if (b.Pieces[j, i].OwnedByWhite == true && b.Pieces[j, i].Location.X < 9)
                        {
                            toReturn[0] += 1;
                        }
                        else if (b.Pieces[j, i].OwnedByWhite = false && b.Pieces[j, i].Location.X < 7)
                        {
                            toReturn[1] += 0.5;
                        }
                        else if (b.Pieces[j, i].OwnedByWhite == false && b.Pieces[j, i].Location.X < 9)
                        {
                            toReturn[1] += 1;
                        }
                    }
                }
            }
            return toReturn;
        }

        /*
              private void valueBoardPosition(ref double blackOpinion, ref double whiteOpinion, State b)
        {
            Piece[,] board = b.Pieces;
            int whitePieces = 0;
            int blackPieces = 0;
            int squareWhitePieces = 0;
            int squareBlackPieces = 0;
            int whiteAdjacency = 0;
            int blackAdjacency = 0;
            int lastPiece = 0; //0 equals no data, 1 equals white, 2 equals black


            for (int x = 0; x < 7; x++) //all columns and squares
            {
                whitePieces = 0;
                blackPieces = 0;
                squareWhitePieces = 0;
                squareBlackPieces = 0;
                whiteAdjacency = 0;
                blackAdjacency = 0;
                lastPiece = 0;

                for (int y = 0; y < ((x < 4) ? 4 : 3); y++)
                {
                    if (x < 3 && y < 3)
                    {
                        squareWhitePieces += (board[y, x] != null && board[y, x].OwnedByWhite ? 1 : 0);
                        squareWhitePieces += (board[y, x + 1] != null && board[y, x + 1].OwnedByWhite ? 1 : 0);
                        squareWhitePieces += (board[y + 1, x + 1] != null && board[y + 1, x + 1].OwnedByWhite ? 1 : 0);
                        squareWhitePieces += (board[y + 1, x] != null && board[y + 1, x].OwnedByWhite ? 1 : 0);

                        squareBlackPieces += (board[y, x] != null && !board[y, x].OwnedByWhite ? 1 : 0);
                        squareBlackPieces += (board[y, x + 1] != null && !board[y, x + 1].OwnedByWhite ? 1 : 0);
                        squareBlackPieces += (board[y + 1, x + 1] != null && !board[y + 1, x + 1].OwnedByWhite ? 1 : 0);
                        squareBlackPieces += (board[y + 1, x] != null && !board[y + 1, x].OwnedByWhite ? 1 : 0);

                        if (squareWhitePieces != 0 && squareBlackPieces == 0)
                        {
                            if (squareWhitePieces == 2)
                            {
                                if (!(board[y, x] != null && board[y + 1, x + 1] != null) || (board[y, x + 1] != null && board[y + 1, x] != null))
                                {
                                    whiteOpinion += getPieceUtility(squareWhitePieces, 1, true, true);
                                }
                            }
                            else
                            {
                                whiteOpinion += getPieceUtility(squareWhitePieces, 0, true, true);
                            }
                        }
                        else if (squareWhitePieces == 0 && squareBlackPieces != 0)
                        {
                            if (squareBlackPieces == 2)
                            {
                                if (!(board[y, x] != null && board[y + 1, x + 1] != null) || (board[y, x + 1] != null && board[y + 1, x] != null))
                                {
                                    blackOpinion += getPieceUtility(squareBlackPieces, 1, true, true);
                                }
                            }
                            else
                            {
                                blackOpinion += getPieceUtility(squareBlackPieces, 0, true, true);
                            }
                        }
                    }

                    if (board[y, x] != null)
                    {

                        if (board[y, x].OwnedByWhite)
                        {
                            whitePieces++;

                            if (lastPiece == 1)
                            {
                                whiteAdjacency++;
                            }
                            lastPiece = 1;
                        }
                        else
                        {
                            blackPieces++;

                            if (lastPiece == 2)
                            {
                                blackAdjacency++;
                            }
                            lastPiece = 2;
                        }
                    }
                    else
                    {
                        lastPiece = 0;
                    }
                }

                if ((whitePieces != 0 && blackPieces == 0))
                {
                    whiteOpinion += getPieceUtility(whitePieces, whiteAdjacency, (x < 4), false);
                }
                else if ((whitePieces == 0 && blackPieces != 0))
                {
                    blackOpinion += getPieceUtility(blackPieces, blackAdjacency, (x < 4), false);
                }
            }

            for (int y = 0; y < 4; y++) //rows (4x4)
            {
                whitePieces = 0;
                blackPieces = 0;
                whiteAdjacency = 0;
                blackAdjacency = 0;
                lastPiece = 0;

                for (int x = 0; x < 4; x++)
                {
                    if (board[x, y] != null)
                    {
                        if (board[x, y].OwnedByWhite)
                        {
                            whitePieces++;

                            if (lastPiece == 1)
                            {
                                whiteAdjacency++;
                            }
                            lastPiece = 1;
                        }
                        else
                        {
                            blackPieces++;

                            if (lastPiece == 2)
                            {
                                blackAdjacency++;
                            }
                            lastPiece = 2;
                        }
                    }
                    else
                    {
                        lastPiece = 0;
                    }
                }

                if ((whitePieces != 0 && blackPieces == 0))
                {
                    whiteOpinion += getPieceUtility(whitePieces, whiteAdjacency, true, false);
                }
                else if ((whitePieces == 0 && blackPieces != 0))
                {
                    blackOpinion += getPieceUtility(blackPieces, blackAdjacency, true, false);
                }
            }

            for (int y = 0; y < 3; y++) //rows (3x3)
            {
                whitePieces = 0;
                blackPieces = 0;

                for (int x = 0; x < 3; x++)
                {
                    if (board[x, y] != null)
                    {
                        if (board[x, y].OwnedByWhite)
                        {
                            whitePieces++;
                        }
                        else
                        {
                            blackPieces++;
                        }
                    }
                }

                if ((whitePieces != 0 && blackPieces == 0))
                {
                    whiteOpinion += getPieceUtility(whitePieces, 0, false, false);
                }
                else if ((whitePieces == 0 && blackPieces != 0))
                {
                    blackOpinion += getPieceUtility(blackPieces, 0, false, false);
                }
            }
            //we don't care about other combinations. Although that could be changed (especially if you cut off the enemy)
            //Other combinations should be taken care of by checking the available pieces for each player. We will need to get the
            //scaling right though
        }

        private double getPieceUtility(int pieces, int adjacency, Boolean four, Boolean square)
        {
            double toReturn = 0;

            switch (pieces)
            {
                case 1:
                    {
                        toReturn++;
                    } break;

                case 2:
                    {
                        toReturn += 2;
                        toReturn += ((adjacency == 1 && square) ? 0.5 : 0); //only applicable to squares. 4x4 is taken care of by the squares.
                    } break;

                case 3:
                    {
                        toReturn += 3;
                        toReturn += ((adjacency == 2 && four) ? 0.5 : 0); //Only applicable to 4x4 board
                    } break;

                case 4:
                    {
                        toReturn += 4;
                    } break;
            }
            return toReturn;
        }
         * */
    }
}
